package cn.admin.system.staff.domain;

import cn.admin.common.constant.CacheConstants;
import cn.admin.common.domain.LoginUser;
import cn.admin.common.exceptionInterceptor.exception.ServiceException;
import cn.admin.common.redis.RedisCache;
import cn.admin.common.security.context.AuthenticationContextHolder;
import cn.admin.common.utils.SecurityUtils;
import cn.admin.common.utils.StringUtils;
import cn.admin.system.staff.infrastructure.repository.entity.SysUser;
import cn.admin.system.staff.infrastructure.repository.repository.SysUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.concurrent.TimeUnit;

/**
 * @author YJ
 * @DateTime 2023/2/22 10:29
 */
@Service
public class SysUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private SysUserRepository sysUserRepository;

    @Autowired
    private RedisCache redisCache;

    @Value(value = "${user.password.lockTime}")
    private int lockTime;

    @Value(value = "${user.password.maxRetryCount}")
    private int maxRetryCount;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserRepository.selectSysUserByUserName(username);
        if (StringUtils.isNotNull(sysUser)) {
            throw new ServiceException(500, "登录用户" + username + "不存在");
        }
        if (sysUser.getStatus() == 1) {
            throw new ServiceException(500, "登录用户" + username + "不存在");
        }
        validate(sysUser);
        return createLoginUser(sysUser);
    }

    /**
     * 验证密码
     * @param user 用户名 密码
     */
    public void validate(SysUser user) {
        //获取缓存,用户输入的账号密码
        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
        String username = usernamePasswordAuthenticationToken.getName();
        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
        Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
        if (null == retryCount) {
            retryCount = 0;
        }
        if (retryCount >= maxRetryCount) {
            throw new ServiceException(500, "当前用户已锁定," + lockTime + "分钟后尝试");
        }
        //验证密码
        if (SecurityUtils.matchesPassword(user.getPassword(),password)) {
            redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
            throw new ServiceException(500, "密码错误");
        } else {
            if (redisCache.hasKey(getCacheKey(username))){
                redisCache.deleteObject(getCacheKey(username));
            }
        }
    }


    /**
     * 登录账户密码错误次数缓存键名
     *
     * @param username 用户名
     * @return 缓存键key
     */
    private String getCacheKey(String username) {
        return CacheConstants.PWD_ERR_CNT_KEY + username;
    }

    /**
     * 登录成功,存储用户信息
     * @param sysUser
     * @return UserDetails
     */
    public UserDetails createLoginUser(SysUser sysUser) {
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(sysUser.getUserId());
        loginUser.setDeptId(sysUser.getDeptId());
        loginUser.setUsername(sysUser.getUserName());
        loginUser.setPassword(sysUser.getPassword());
        loginUser.setPermissions(new HashSet<>());
        return loginUser;
    }


}
